package com.rw.coco.handler.message.reply.util;

import com.rw.coco.api.data.CacheMapper;
import com.rw.coco.util.config.CocoConfig;
import com.rw.coco.util.config.CocoOption;

import java.util.Optional;

/**
 * 频率限制工具类
 */
public class FrequencyLimit {
    // 最大警告次数
    public final int maxWarnCount;

    // 警告持续时间，这里的单位是毫秒
    public final long warnTime;

    // 群聊频率指定时间
    public final long groupFreqTime;

    // 群聊频率指定次数
    public final int groupFreqCount;

    // 个人频率指定时间
    public final long privateFreqTime;

    // 个人频率指定次数
    public final int privateFreqCount;

    private final CacheMapper cacheMapper;

    public FrequencyLimit(CocoConfig cocoConfig, CacheMapper cacheMapper) {
        this.cacheMapper = cacheMapper;

        CocoOption cocoOption = cocoConfig.getCocoOption();
        this.maxWarnCount = cocoOption.optionProp.getInt(CocoOption.MAX_WARN_COUNT);
        this.warnTime = cocoOption.optionProp.getLong(CocoOption.WARN_TIME) * 24 * 60 * 60 * 1000;
        this.groupFreqTime = cocoOption.optionProp.getLong(CocoOption.GROUP_FREQ_TIME);
        this.groupFreqCount = cocoOption.optionProp.getInt(CocoOption.GROUP_FREQ_COUNT);
        this.privateFreqTime = cocoOption.optionProp.getLong(CocoOption.PRIVATE_FREQ_TIME);
        this.privateFreqCount = cocoOption.optionProp.getInt(CocoOption.PRIVATE_FREQ_COUNT);
    }

    /**
     * 增加一次访问频率计数，并返回群组频率是否超频
     */
    public boolean countGroupFreq(String token) {
        return countFreq(token, groupFreqTime, groupFreqCount);
    }

    /**
     * 增加一次访问频率计数，并返回私聊频率是否超频
     */
    public boolean countPrivateFreq(String token) {
        return countFreq(token, privateFreqTime, privateFreqCount);
    }

    private boolean countFreq(String token, long freqTime, int freqCount) {
        // 如果允许的访问次数小于等于1，则每次访问都超频
        if (freqCount <= 1) {
            return true;
        }

        Optional<Integer> optional = cacheMapper.get(token);
        // 如果没有频率信息，则加入频率
        if (!optional.isPresent()) {
            cacheMapper.save(token, 1, freqTime);
            return false;
        }

        // 如果有频率信息，则增加计数
        int count = optional.get() + 1;
        // 如果超频，则清除计数
        if (count >= freqCount) {
            cacheMapper.delete(token);
            return true;
        }

        // 未过频，记录计数
        cacheMapper.increment(token);
        return false;
    }

    /**
     * 增加，并获取警告次数
     */
    public int warn(String token) {
        Optional<Integer> optional = cacheMapper.get(token);
        // 如果没有频率信息，则加入警告次数
        if (!optional.isPresent()) {
            cacheMapper.save(token, 1, warnTime);
            return 1;
        }

        // 获取，并增加计数
        return cacheMapper.increment(token).orElse(0);
    }
}
